using UnityEngine;
using System.Collections;

public class checkRule : ScriptableObject{
	#region các hàm kiểm tra các nước cờ có thể đi
	static public bool Phai(int i, int j, int[,] A, int x)
	{
		if (A[i, j + 1] + x == 0)
		{
			for (int k = j + 2; k < 8; k++)
			{
				if (A[i, k] == x) return true;
				if (A[i, k] + x == 0) continue;
				if (A[i, k] == 0) return false;
			}
		}
		return false;
	}
	static public bool Trai(int i, int j, int[,] A, int x)
	{
		if (A[i, j - 1] + x == 0)
		{
			for (int k = j - 2; k >= 0; k--)
			{
				if (A[i, k] == x) return true;
				if (A[i, k] + x == 0) continue;
				if (A[i, k] == 0) return false;
			}
		}
		return false;
	}
	static public bool Tren(int i, int j, int[,] A, int x)
	{
		if (A[i - 1, j] + x == 0)
		{
			for (int k = i - 2; k >= 0; k--)
			{
				if (A[k, j] == x) return true;
				if (A[k, j] + x == 0) continue;
				if (A[k, j] == 0) return false;
			}
		}
		return false;
	}
	static public bool Duoi(int i, int j, int[,] A, int x)
	{
		if (A[i + 1, j] + x == 0)
		{
			for (int k = i + 2; k < 8; k++)
			{
				if (A[k, j] == x) return true;
				if (A[k, j] + x == 0) continue;
				if (A[k, j] == 0) return false;
			}
		}
		return false;
	}
	
	static public bool Tren_Trai(int i, int j, int[,] A, int x)
	{
		if (A[i - 1, j - 1] + x == 0)
		{
			for (int k = i - 2, t = j - 2; k >= 0 && t >= 0; k--, t--)
			{
				if (A[k, t] == x) return true;
				if (A[k, t] + x == 0) continue;
				if (A[k, t] == 0) return false;
			}
		}
		return false;
	}
	static public bool Tren_Phai(int i, int j, int[,] A, int x)
	{
		if (A[i - 1, j + 1] + x == 0)
		{
			for (int k = i - 2, t = j + 2; k >= 0 && t < 8; k--, t++)
			{
				if (A[k, t] == x) return true;
				if (A[k, t] + x == 0) continue;
				if (A[k, t] == 0) return false;
			}
		}
		return false;
	}
	static public bool Duoi_Trai(int i, int j, int[,] A, int x)
	{
		if (A[i + 1, j - 1] + x == 0)
		{
			for (int k = i + 2, t = j - 2; k < 8 && t >= 0; k++, t--)
			{
				if (A[k, t] == x) return true;
				if (A[k, t] + x == 0) continue;
				if (A[k, t] == 0) return false;
			}
		}
		return false;
	}
	static public bool Duoi_Phai(int i, int j, int[,] A, int x)
	{
		if (A[i + 1, j + 1] + x == 0)
		{
			for (int k = i + 2, t = j + 2; k < 8 && t < 8; k++, t++)
			{
				if (A[k, t] == x) return true;
				if (A[k, t] + x == 0) continue;
				if (A[k, t] == 0) return false;
			}
		}
		return false;
	}
	#endregion
	#region các hàm biến đổi trạng thái theo từng nước cờ
	static public void Change_Phai(int[,] A, int x, int i, int j)
	{
		for (int k = j + 1; k < 8; k++)
		{
			A[i, k] = x;
			if (A[i, k + 1] == x) break;
		}
	}
	static public void Change_Trai(int[,] A, int x, int i, int j)
	{
		for (int k = j - 1; k >= 0; k--)
		{
			A[i, k] = x;
			if (A[i, k - 1] == x) break;
		}
	}
	static public void Change_Tren(int[,] A, int x, int i, int j)
	{
		for (int k = i - 1; k >= 0; k--)
		{
			A[k, j] = x;
			if (A[k - 1, j] == x) break;
		}
	}
	static public void Change_Duoi(int[,] A, int x, int i, int j)
	{
		for (int k = i + 1; k < 8; k++)
		{
			A[k, j] = x;
			if (A[k + 1, j] == x) break;
		}
	}
	
	static public void Change_Tren_Trai(int[,] A, int x, int i, int j)
	{
		for (int k = i - 1, t = j - 1; k >= 0 && t >= 0; k--, t--)
		{
			A[k, t] = x;
			if (A[k - 1, t - 1] == x) break;
		}
	}
	static public void Change_Duoi_Trai(int[,] A, int x, int i, int j)
	{
		for (int k = i + 1, t = j - 1; k < 8 && t >= 0; k++, t--)
		{
			A[k, t] = x;
			if (A[k + 1, t - 1] == x) break;
		}
	}
	static public void Change_Tren_Phai(int[,] A, int x, int i, int j)
	{
		for (int k = i - 1, t = j + 1; k >= 0 && t < 8; k--, t++)
		{
			A[k, t] = x;
			if (A[k - 1, t + 1] == x) break;
		}
	}
	static public void Change_Duoi_Phai(int[,] A, int x, int i, int j)
	{
		for (int k = i + 1, t = j + 1; k < 8 && t < 8; k++, t++)
		{
			A[k, t] = x;
			if (A[k + 1, t + 1] == x) break;
		}
	}
	#endregion

	static public int[,] Test(int[,] A, int x) //Tra ve ma tran, them cac so 2 bieu thi di dc.
	{
		int[,] B = new int[8, 8];
		for(int k=0;k<8;k++){
			for(int l=0;l<8;l++){
				B[k,l]=A[k,l];
			}
		}
		//B=A;
		for (int i = 0; i < 8; i++)
		{
			for (int j = 0; j < 8; j++)
			{
				if (B[i, j] == 0)
				{
					if (i <= 1)
					{
						if (j <= 1)
						{
							if (Phai(i, j, B, x)) B[i, j] = 2;
							if (Duoi(i, j, B, x)) B[i, j] = 2;
							if (Duoi_Phai(i, j, B, x)) B[i, j] = 2;
						}
						else if (j >= 6)
						{
							if (Trai(i, j, B, x)) B[i, j] = 2;
							if (Duoi(i, j, B, x)) B[i, j] = 2;
							if (Duoi_Trai(i, j, B, x)) B[i, j] = 2;
						}
						else
						{
							if (Trai(i, j, B, x)) B[i, j] = 2;
							if (Phai(i, j, B, x)) B[i, j] = 2;
							if (Duoi(i, j, B, x)) B[i, j] = 2;
							if (Duoi_Phai(i, j, B, x)) B[i, j] = 2;
							if (Duoi_Trai(i, j, B, x)) B[i, j] = 2;
						}
					}
					else if (i >= 6)
					{
						if (j <= 1)
						{
							if (Phai(i, j, B, x)) B[i, j] = 2;
							if (Tren(i, j, B, x)) B[i, j] = 2;
							if (Tren_Phai(i, j, B, x)) B[i, j] = 2;
						}
						else if (j >= 6)
						{
							if (Trai(i, j, B, x)) B[i, j] = 2;
							if (Tren(i, j, B, x)) B[i, j] = 2;
							if (Tren_Trai(i, j, B, x)) B[i, j] = 2;
						}
						else
						{
							if (Trai(i, j, B, x)) B[i, j] = 2;
							if (Phai(i, j, B, x)) B[i, j] = 2;
							if (Tren(i, j, B, x)) B[i, j] = 2;
							if (Tren_Phai(i, j, B, x)) B[i, j] = 2;
							if (Tren_Trai(i, j, B, x)) B[i, j] = 2;
						}
						
					}
					else
					{
						if (j <= 1)
						{
							if (Phai(i, j, B, x)) B[i, j] = 2;
							if (Tren(i, j, B, x)) B[i, j] = 2;
							if (Duoi(i, j, B, x)) B[i, j] = 2;
							if (Tren_Phai(i, j, B, x)) B[i, j] = 2;
							if (Duoi_Phai(i, j, B, x)) B[i, j] = 2;
						}
						else if (j >= 6)
						{
							if (Trai(i, j, B, x)) B[i, j] = 2;
							if (Tren(i, j, B, x)) B[i, j] = 2;
							if (Duoi(i, j, B, x)) B[i, j] = 2;
							if (Tren_Trai(i, j, B, x)) B[i, j] = 2;
							if (Duoi_Trai(i, j, B, x)) B[i, j] = 2;
						}
						else
						{
							if (Phai(i, j, B, x)) B[i, j] = 2;
							if (Trai(i, j, B, x)) B[i, j] = 2;
							if (Tren(i, j, B, x)) B[i, j] = 2;
							if (Duoi(i, j, B, x)) B[i, j] = 2;
							if (Tren_Trai(i, j, B, x)) B[i, j] = 2;
							if (Tren_Phai(i, j, B, x)) B[i, j] = 2;
							if (Duoi_Trai(i, j, B, x)) B[i, j] = 2;
							if (Duoi_Phai(i, j, B, x)) B[i, j] = 2;
						}
					}
				}
			}
		}
		return B;
	}

	public static int[,] Danh_x(int[,] A, int x, int i, int j)
	{
		int[,] B = new int[8, 8];
		int[,] C = new int[8,8];
		C=Test(A,x);
		//B=Test(A,x);
		for(int k=0;k<8;k++){
			for(int l=0;l<8;l++){
				B[k,l]=C[k,l];
			}
		}
		if (B[i, j] == 2)
		{
            Del_2(B);
			if (i <= 1)
			{
				if (j <= 1)
				{
					if (Phai(i, j, B, x)) Change_Phai(B, x, i, j);
					if (Duoi(i, j, B, x)) Change_Duoi(B, x, i, j);
					if (Duoi_Phai(i, j, B, x)) Change_Duoi_Phai(B, x, i, j);
				}
				else if (j >= 6)
				{
					if (Trai(i, j, B, x)) Change_Trai(B, x, i, j);
					if (Duoi(i, j, B, x)) Change_Duoi(B, x, i, j);
					if (Duoi_Trai(i, j, B, x)) Change_Duoi_Trai(B, x, i, j);
				}
				else
				{
					if (Trai(i, j, B, x)) Change_Trai(B, x, i, j);
					if (Phai(i, j, B, x)) Change_Phai(B, x, i, j);
					if (Duoi(i, j, B, x)) Change_Duoi(B, x, i, j);
					if (Duoi_Phai(i, j, B, x)) Change_Duoi_Phai(B, x, i, j);
					if (Duoi_Trai(i, j, B, x)) Change_Duoi_Trai(B, x, i, j);
				}
			}
			else if (i >= 6)
			{
				if (j <= 1)
				{
					if (Phai(i, j, B, x)) Change_Phai(B, x, i, j);
					if (Tren(i, j, B, x)) Change_Tren(B, x, i, j);
					if (Tren_Phai(i, j, B, x)) Change_Tren_Phai(B, x, i, j);
				}
				else if (j >= 6)
				{
					if (Trai(i, j, B, x)) Change_Trai(B, x, i, j);
					if (Tren(i, j, B, x)) Change_Tren(B, x, i, j);
					if (Tren_Trai(i, j, B, x)) Change_Tren_Trai(B, x, i, j);
				}
				else
				{
					if (Trai(i, j, B, x)) Change_Trai(B, x, i, j);
					if (Phai(i, j, B, x)) Change_Phai(B, x, i, j);
					if (Tren(i, j, B, x)) Change_Tren(B, x, i, j);
					if (Tren_Phai(i, j, B, x)) Change_Tren_Phai(B, x, i, j);
					if (Tren_Trai(i, j, B, x)) Change_Tren_Trai(B, x, i, j);
				}
				
			}
			else
			{
				if (j <= 1)
				{
					if (Phai(i, j, B, x)) Change_Phai(B, x, i, j);
					if (Tren(i, j, B, x)) Change_Tren(B, x, i, j);
					if (Duoi(i, j, B, x)) Change_Duoi(B, x, i, j);
					if (Tren_Phai(i, j, B, x)) Change_Tren_Phai(B, x, i, j);
					if (Duoi_Phai(i, j, B, x)) Change_Duoi_Phai(B, x, i, j);
				}
				else if (j >= 6)
				{
					if (Trai(i, j, B, x)) Change_Trai(B, x, i, j);
					if (Tren(i, j, B, x)) Change_Tren(B, x, i, j);
					if (Duoi(i, j, B, x)) Change_Duoi(B, x, i, j);
					if (Tren_Trai(i, j, B, x)) Change_Tren_Trai(B, x, i, j);
					if (Duoi_Trai(i, j, B, x)) Change_Duoi_Trai(B, x, i, j);
				}
				else
				{
					if (Phai(i, j, B, x)) Change_Phai(B, x, i, j);
					if (Trai(i, j, B, x)) Change_Trai(B, x, i, j);
					if (Tren(i, j, B, x)) Change_Tren(B, x, i, j);
					if (Duoi(i, j, B, x)) Change_Duoi(B, x, i, j);
					if (Tren_Trai(i, j, B, x)) Change_Tren_Trai(B, x, i, j);
					if (Tren_Phai(i, j, B, x)) Change_Tren_Phai(B, x, i, j);
					if (Duoi_Trai(i, j, B, x)) Change_Duoi_Trai(B, x, i, j);
					if (Duoi_Phai(i, j, B, x)) Change_Duoi_Phai(B, x, i, j);
				}
			}
            B[i, j] = x;
		}
		else Debug.Log("Toa do khong = 2");
		
		//B[i, j] = x;
		//Del_2(B);
		return B;
	}
	static void Del_2(int[,] A)
	{
		for (int i = 0; i < 8; i++)
			for (int j = 0; j < 8; j++)
		{
			if (A[i, j] == 2) A[i, j] = 0;
		}
	}

	//upadate ngay 12/01/2014

	//=========================================================================================
	static public int Count_2(int[,] A)
	{
		int Count = 0;
		for (int i = 0; i < 8; i++)
			for (int j = 0; j < 8; j++)
		{
			if (A[i, j] == 2) Count++;
		}
		return Count;
	}

	static public int Heuristic(int[,] A, Vector2 P, int x) //P la nuoc di dan den trang thai A, x-tai trang thai do la ai di (goi them vao de heuristic gioi hon)
	{
		int mot = 0;
		int _mot = 0;
		for (int i = 0; i < 8; i++)
		{
			for (int j = 0; j < 8; j++)
			{
				if (A[i, j] == 1) mot++;
				else if(A[i,j] == -1) _mot++;
			}
		}
		int kq = mot - _mot;

		if (P.x == 0 || P.x == 7 || P.y == 0 || P.y == 7) //tăng điểm cho trạng thái khi đánh vào ô biên.
			kq += 5; 

		if (((P.x == 1 || P.x == 6) && P.y < 7 && P.y > 0) || ((P.y == 1 || P.y == 6) && P.x < 7 && P.x > 0)) //giam diem cho trang thai khi danh vao ô kề biên.
			kq -= 3;

		if (x == 1) return (_mot - mot);
		return (mot - _mot);
	}
	static public int Minimax(int alpha, int beta, Vector2 P, int depth, int[,] A, int x)//den x di, ma tran A sau khi -x di vao P
	{
		int best;
		if (depth == 0 || Count_2(Test(A,x)) == 0) return Heuristic(A,P,x);
		else
		{
			best = -1000;
			int [,] B = Test(A,x);
			for (int i = 0; i < 8; i++)
			{
				for (int j = 0; j < 8; j++)
				{
					if (B[i, j] == 2 && best < beta)
					{
						if (best > alpha) alpha = best;
						int[,] C = Danh_x(A, x, i, j);
						Vector2 p = new Vector2(i, j);
						int value = -Minimax(-beta,-alpha,p,depth - 1, C, -x);//đệ quy và đổi dấu
						if (value > best) best = value;
					}
				}
			}
		}
		return best;
	}
	
	static public Vector2 AI(int x, int[,] A, int D)//A Trang thai hien tai, den x di; tra ve toa do can di. độ khó D, từ 0 - 3
	{
		int[,] B = Test(A, x);
		int max = -1000;
		Vector2 Ai = new Vector2();



		for (int i = 0; i < 8; i++)
		{
			for (int j = 0; j < 8; j++)
			{
				if (B[i, j] == 2)
				{
					Vector2 P = new Vector2(i,j);
					int k = Minimax(-1000,1000,P,D*2,Danh_x(A,x,i,j),-x);
                    
					if (max < k) { max = k; Ai.x = i; Ai.y = j; } 
				}
			}
		}
		return Ai;
	}


	// ======== Update ham Kiêm tra xem ván cờ đã kết thúc hay chưa.
	// sau mỗi nước đi đều gọi hàm này, A là trạng thái hiện tại của bàn cờ.

	static public int Ch_Win(int[,] A) //Kiem tra trang thai hien tai co phai trang thai ket thuc hay chua va tra ve xem 1 hay -1 thang, hay HOA thi tra ve 0
	{//tra ve 2 la chua ket thuc.
		int mot = 0; //1
		int _mot = 0; //-1
		if (Count_2(Test(A, 1)) == 0 && Count_2(Test(A, -1)) == 0) // ca 2 ben deu khong con nuoc di hop le.
		{
			for (int i = 0; i < 8; i++)
			{
				for (int j = 0; j < 8; j++)
				{
					if (A[i, j] == 1) mot++;
					if (A[i, j] == -1) _mot++;
				}
			}
			if (mot > _mot) return 1; // 1 Win
			else if (mot < _mot) return -1; // -1 win
			else return 0; // hoa
		}
		return 2; //van co chua ket thuc.
	}
}
